package com.sxkf.template.service.impl;

import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sxkf.template.constants.CommonConstants;
import com.sxkf.template.dto.EvaluationDto;
import com.sxkf.template.entity.*;
import com.sxkf.template.mapper.AfterSaleEvaluationMapper;
import com.sxkf.template.mapper.ProductMapper;
import com.sxkf.template.mapper.StoreEvaluationMapper;
import com.sxkf.template.mapper.StoreMapper;
import com.sxkf.template.service.CouponService;
import com.sxkf.template.service.StoreEvaluationService;
import com.sxkf.template.service.StoreService;
import com.sxkf.template.vo.request.store.QueryStoreVo;
import org.jeecg.common.exception.SxkfException;
import org.jeecg.common.util.CheckEmptyUtil;
import org.jeecg.common.util.RedisUtil;
import org.jeecg.common.util.RedisUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class StoreServiceImpl extends ServiceImpl<StoreMapper, Store> implements StoreService {

    @Resource
    private ProductMapper productMapper;

    @Resource
    private CouponService couponService;

    @Resource
    private RedisUtils redisUtils;

    @Resource
    private StoreEvaluationMapper storeEvaluationMapper;

    @Resource
    private AfterSaleEvaluationMapper afterSaleEvaluationMapper;


    @Override
    public IPage<Store> listNearby(Double longitude, Double latitude, Integer pageNo, Integer pageSize) {
        return baseMapper.findNearbyStores(new Page<>(pageNo, pageSize), null, latitude, longitude);
    }

    @Override
    public IPage<Store> listByStore(QueryStoreVo queryStoreVo) {

        // 存缓存
        if (CheckEmptyUtil.isNotEmpty(queryStoreVo.getStoreName()) && CheckEmptyUtil.isNotEmpty(queryStoreVo.getUserId())) {
            List<String> hisSearch = redisUtils.lGet(CommonConstants.HIS_SEARCH + ":" + queryStoreVo.getUserId(), 0, -1);
            if (hisSearch != null && !hisSearch.contains(queryStoreVo.getStoreName())) {
                redisUtils.lSet(CommonConstants.HIS_SEARCH+":"+queryStoreVo.getUserId(), queryStoreVo.getStoreName());
            }
            // 搜索发现
            Double score = redisUtils.score(CommonConstants.SEARCH_FIND, queryStoreVo.getStoreName());
            if (score != null) {
                redisUtils.incrementScore(CommonConstants.SEARCH_FIND,queryStoreVo.getStoreName(),1);
            }else {
                redisUtils.addZset(CommonConstants.SEARCH_FIND,queryStoreVo.getStoreName(),0);
            }

        }


        Page<Store> page = new Page<>(queryStoreVo.getPageNo(), queryStoreVo.getPageSize());

        LambdaQueryWrapper<Store> queryWrapper = new LambdaQueryWrapper<Store>()
                .like(CheckEmptyUtil.isNotEmpty(queryStoreVo.getStoreName()), Store::getName, queryStoreVo.getStoreName())
                .eq(CheckEmptyUtil.isNotEmpty(queryStoreVo.getStoreType()),Store::getType,queryStoreVo.getStoreType())
                .eq(CheckEmptyUtil.isNotEmpty(queryStoreVo.getCategoryId()),Store::getCategoryId,queryStoreVo.getCategoryId());

        IPage<Store> result;
        if ("1".equals(queryStoreVo.getSearchType())){
            result = baseMapper.findNearbyStores(page,queryWrapper,queryStoreVo.getLatitude(),queryStoreVo.getLongitude());
        }else {
            queryWrapper.orderByDesc("3".equals(queryStoreVo.getSearchType()),Store::getCreateTime);
            queryWrapper.orderByDesc("2".equals(queryStoreVo.getSearchType()),Store::getFansCount);
            result = page(page, queryWrapper);
        }

        List<String> storeIdList = result.getRecords()
                .stream()
                .map(Store::getId)
                .collect(Collectors.toList());

        List<Coupon> couponList = couponService.list(new LambdaQueryWrapper<Coupon>()
                .in(CheckEmptyUtil.isNotEmpty(storeIdList),Coupon::getStoreId, storeIdList));

        Map<String, List<Coupon>> couponListMap = couponList.stream().collect(Collectors.groupingBy(Coupon::getStoreId));


        result.getRecords().forEach(store->{
            List<Product> productList = productMapper.selectList(new LambdaQueryWrapper<Product>()
                    .eq(Product::getStoreId, store.getId())
                    .orderByDesc(Product::getSaleCount)
                    .last("limit 9")
            );
            store.setProductList(productList);

            // 优惠卷
            store.setCouponList(couponListMap.get(store.getId()));

        });
        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean evaluation(String storeId, String userId, Double evaluation) {

        StoreEvaluation storeEvaluation = new StoreEvaluation();
        storeEvaluation.setStoreId(storeId);
        storeEvaluation.setUserId(userId);
        storeEvaluation.setEvaluation(evaluation);
        int insert = storeEvaluationMapper.insert(storeEvaluation);
        if (insert > 0) {

            EvaluationDto evaluationDto = storeEvaluationMapper.getRecordSum(storeId);
            double avg = getAvgEvaluation(storeId, BigDecimal.ZERO, 0L, BigDecimal.valueOf(evaluationDto.getEvaluation()), (long) evaluationDto.getCount());
            boolean update = update(new LambdaUpdateWrapper<Store>()
                    .set(Store::getUserEvalution, evaluationDto.getEvaluation() / evaluationDto.getCount())
                    .set(Store::getAvgEvalution,avg)
                    .eq(Store::getId, storeId)
            );
            return update;
        }

        throw new SxkfException("评分失败");

    }


    public double getAvgEvaluation(String storeId, BigDecimal soldEvaluation, Long soldCount, BigDecimal userEvaluation, Long userCount) {

        // soldCount为0
        if (soldCount == 0L){

            EvaluationDto evaluationDto = afterSaleEvaluationMapper.getRecordSum(storeId);
            System.out.println("soldCount为0 evaluationDto = " + JSON.toJSONString(evaluationDto));
            return BigDecimal.valueOf(evaluationDto.getEvaluation()).add(userEvaluation).divide(BigDecimal.valueOf(evaluationDto.getCount()).add(BigDecimal.valueOf(userCount)), RoundingMode.FLOOR).doubleValue();

//            long count = afterSaleEvaluationMapper.selectCount(new LambdaQueryWrapper<AfterSaleEvaluation>()
//                    .eq(AfterSaleEvaluation::getStoreId, storeId)
//            );
//            List<Object> results = afterSaleEvaluationMapper.selectObjs(new QueryWrapper<AfterSaleEvaluation>()
//                    .select("SUM(star) as total")
//            );
//            String afterSaleEvaluation = results.get(0).toString();
//            return BigDecimal.valueOf(Double.parseDouble(afterSaleEvaluation)).add(userEvaluation).divide(BigDecimal.valueOf(count).add(BigDecimal.valueOf(userCount)), RoundingMode.FLOOR).doubleValue();
        }

        // userCount为0
        if (userCount == 0L){
            EvaluationDto evaluationDto = storeEvaluationMapper.getRecordSum(storeId);
            System.out.println("userCount为0 evaluationDto = " + JSON.toJSONString(evaluationDto));
            return BigDecimal.valueOf(evaluationDto.getEvaluation()).add(soldEvaluation).divide(BigDecimal.valueOf(evaluationDto.getCount()).add(BigDecimal.valueOf(soldCount)), RoundingMode.FLOOR).doubleValue();

        }

        return 0.0;

    }



}
